package de.koller.singularity.engine.tile;

import de.koller.aframe.util.resource.IOLoader;
import de.koller.oceanFramework.util.MIn;
import de.koller.oceanFramework.util.MOut;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class TileMapSave {

	public static final int CHUNK_SIZE = 512;
	public static final String SAVE_PATH = "./save/singularity/map/";
	private final long mx, my;
	private final String system;
	
	private long lastTimeUsed = 0;
	
	private final STile[][][] map = new STile[ CHUNK_SIZE ][ CHUNK_SIZE ][ 0 ];

	public TileMapSave( String system, long mx, long my, TileCreator creator ) {
		this.mx = mx;
		this.my = my;
		this.system = system;
		
		for( int x = 0; x < map.length; x++ )
			for( int y = 0; y < map[x].length; y++ )
				map[x][y] = new STile[] { creator.getTile( "grid" ) };
		
		load( creator );
	}
	
	public boolean isInBounds( String system, long tx, long ty ) {
		if( !system.equals( this.system ) )
			return false;
		
		int rx = (int)( tx - mx );
		int ry = (int)( ty - my );
		
		if( rx < 0 || ry < 0 || rx >= CHUNK_SIZE || ry >= CHUNK_SIZE )
			return false;
		
		return true;
	}
	
	public STile[] getTile( String system, long tx, long ty ) {
		if( !system.equals( this.system ) )
			return null;
		
		int rx = (int)( tx - mx );
		int ry = (int)( ty - my );
		
		if( rx < 0 || ry < 0 || rx >= CHUNK_SIZE || ry >= CHUNK_SIZE )
			return null;
		
		return map[ rx ][ ry ];
	}
	
	public void setTile( String system, long tx, long ty, STile... tiles ) {
		if( !system.equals( this.system ) )
			return;
		
		int rx = (int)( tx - mx );
		int ry = (int)( ty - my );
		
		if( rx < 0 || ry < 0 || rx >= CHUNK_SIZE || ry >= CHUNK_SIZE )
			return;
		
		map[ rx ][ ry ] = tiles;
	}
	
	public void load( TileCreator creator ) {
		InputStream is;
		try {
			is = IOLoader.getCompressedInputStream( 
				SAVE_PATH + "/" + system + "/c_" + mx + "_" + my + ".map" );
		} catch( Exception ex ) {
			return;
		}
		
		MIn in = new MIn( is );
		if( in.readInt( 1 )[0] != CHUNK_SIZE ) return;
		
		String[] ref = in.readString( in.readInt(1)[0] );
		for( int x = 0; x < map.length; x++ )
			for( int y = 0; y < map[x].length; y++ ) {
				int layer = in.readInt( 1 )[0];
				if( layer == 0 ) continue;
				
				STile[] tiles = new STile[ layer ];
				for( int j = 0; j < tiles.length; j++ )
					tiles[j] = creator.getTile( ref[ in.readInt(1)[0] - 1 ] );
				map[x][y] = tiles;
			}
		
		if( !in.readString(1)[0].equals( "end" ) )
			System.err.println( "something went wrong while loading!" );
		
		in.close();
	}
	
	public void save() {
		List<String> ref = new ArrayList<>();
		
		for( int x = 0; x < map.length; x++ )
			for( int y = 0; y < map[x].length; y++ )
				for( int j = 0; j < map[x][y].length; j++ ) {
					if( map[x][y][j] == null ) continue;
					String n = map[x][y][j].typeName;
					if( ref.contains( n ) ) continue;
					ref.add( n );
				}
		
		OutputStream os = IOLoader.getCompressedOutputStream( 
				SAVE_PATH + "/" + system + "/c_" + mx + "_" + my + ".map" );
		MOut out = new MOut( os );
		out.writeInt( CHUNK_SIZE );
		
		out.writeInt( ref.size() );
		for( String s : ref )
			out.writeString( s );
		
		for( int x = 0; x < map.length; x++ )
			for( int y = 0; y < map[x].length; y++ ) {
				out.writeInt( map[x][y].length );
				for( int j = 0; j < map[x][y].length; j++ ) {
					String n = map[x][y][j].typeName;
					out.writeInt( ref.indexOf( n ) + 1 );
				}
			}
		
		out.writeString( "end" );
		out.close();
	}

	public long getLastTimeUsed() {
		return lastTimeUsed;
	}

	public void setLastTimeUsed( long lastTimeUsed ) {
		this.lastTimeUsed = lastTimeUsed;
	}
	
}
